package com.fzsf.drawingboard.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.fzsf.drawingboard.bean.SerializablePath;
import com.fzsf.drawingboard.utils.BitmapUtils;
import com.fzsf.drawingboard.utils.PressureUtils;
import com.fzsf.drawingboard.utils.ScreenUtils;
import com.fzsf.drawingboard.R;

import java.util.LinkedList;

/**
 * Created by Taijl on 2017/12/13.
 * 支持多字书写的 绘板
 */
public class MultiWritingBoard extends View {
    private static final float STROKEWIDTH = 5f;

    private Canvas mCanvas;
    private Paint mPaint = new Paint();
    private Paint mPaint2 = new Paint();
    private Bitmap mBitmap;
    private LinkedList<SerializablePath> paths = new LinkedList<>();
    Path path = new Path();
    private boolean isWriting = false;
    /**
     * 手写板分辨率到屏幕放缩比例
     */
    private float ratio = 1f;
    /**
     * 手写笔画起点的坐标
     */
    private float touchStartX = 0, touchStartY = 0;
    /**
     * 手写板上写字笔画的起点坐标
     */
    private int writingStartX = -1, writingStartY = -1;
    /**
     * 手写板上写字当前绘制的中点坐标
     */
    float viewMiddleX = -1, viewMiddleY = -1;
    /**
     * 手写板上写每个字的起点坐标
     */
    float firstPoint[] = null;
    /**
     * View上图像最小点坐标和最大点坐标
     */
    float[] viewMinCoordinate = new float[]{-1, -1}, viewMaxCoordinate = new float[]{-1, -1};

    public MultiWritingBoard(Context context) {
        this(context, null);
    }

    public MultiWritingBoard(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MultiWritingBoard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        initView();
    }

    private void initView() {
        setBackgroundResource(R.color.white);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setStrokeWidth(STROKEWIDTH);//线宽
        mPaint.setStrokeCap(Paint.Cap.ROUND);//结束的笔画为圆心
        mPaint.setStrokeJoin(Paint.Join.ROUND);//连接处元
        mPaint.setAlpha(255);

        mPaint2.setAntiAlias(true);
        mPaint2.setColor(Color.BLACK);
        mPaint2.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint2.setStrokeWidth(2f);//线宽
        mPaint2.setAlpha(255);
        mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);

        ratio = Math.max(9800 / ScreenUtils.getWidth(), 13000 / ScreenUtils.getHeight());
        if (ratio < 1) {
            ratio = 1;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.TRANSPARENT);
        canvas.drawBitmap(mBitmap, 0, 0, mPaint2);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStartX = event.getX();
                touchStartY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                drawLine(touchStartX, touchStartY, x, y);
                touchStartX = x;
                touchStartY = y;
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

    /**
     * 直接手写画线
     */
    private void drawLine(float sx, float sy, float ex, float ey) {
        mCanvas.drawLine(sx, sy, ex, ey, mPaint2);
        invalidate();
    }

    /**
     * 重置绘板
     */
    public void reSetBoard() {
        writingStartX = -1;
        writingStartY = -1;
        paths.clear();
        mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        initView();
        invalidate();
        firstPoint = null;
        viewMinCoordinate = new float[]{-1, -1};
        viewMaxCoordinate = new float[]{-1, -1};
    }

    /**
     * 使用手写板书写
     */
    public void writeByWritingPad(int x, int y, int z) {
        Log.e("writeByWritingPad ", x + " " + y + "    -->" + z);
        if (z <= 100) {
            if (isWriting) {
                penUp();
            } else {
                penDown(x, y);
            }
            return;
        }
        penMove(x, y, z);
    }


    /**
     * 书写
     */
    private void penMove(int x, int y, int z) {
        if (null != paths && paths.size() > 0) {
            if (null == firstPoint) {
                firstPoint = new float[]{x, y};
            }
            paths.getLast().addPathPoints(new float[]{x, y});
        }

        if (writingStartY != -1 && writingStartX != -1) {
            calculateAlphaAndStrokeWidth(z);
            drawZoomLine(writingStartX, writingStartY, x, y);
            invalidate();
        }
        writingStartX = x;
        writingStartY = y;
    }

    /**
     * 根据压感计算 透明度和宽度
     */
    private void calculateAlphaAndStrokeWidth(int z) {
        PressureUtils.addPressure(z);
        z = PressureUtils.getValidPressure();
        if (null == mPaint) {
            return;
        }
        if (z > 1500) {
            mPaint.setAlpha(255);
            mPaint.setStrokeWidth(STROKEWIDTH);//线宽
        } else {
            mPaint.setAlpha(255 * z / 1500);
            float v = STROKEWIDTH * z / 1500;
            mPaint.setStrokeWidth(v < 1 ? 1 : v);//线宽
        }
    }

    /**
     * 抬笔
     */
    private void penUp() {
        isWriting = false;
        writingStartX = -1;
        writingStartY = -1;
        viewMiddleX = -1;
        viewMiddleY = -1;
        PressureUtils.clearPressureList();
    }

    /**
     * 绘制带放缩之后的线条
     */
    private void drawZoomLine(int writingStartX, int writingStartY, float aFloat, float aFloat1) {
        float viewX0 = calculateViewLocation(new float[]{writingStartX, writingStartY})[0];
        float viewY0 = calculateViewLocation(new float[]{writingStartX, writingStartY})[1];
        float viewX1 = calculateViewLocation(new float[]{aFloat, aFloat1})[0];
        float viewY1 = calculateViewLocation(new float[]{aFloat, aFloat1})[1];

        if (-1 == viewMiddleX) {
            viewMiddleX = (viewX0 + viewX1) / 2;
            viewMiddleY = (viewY0 + viewY1) / 2;
            path.moveTo(viewX0, viewY0);
        } else {
            path.moveTo(viewMiddleX, viewMiddleY);
        }

        float newMiddleX = (viewX0 + viewX1) / 2;
        float newMiddleY = (viewY0 + viewY1) / 2;
        path.quadTo(viewX0, viewY0, newMiddleX, newMiddleY);
        path.close();
        mCanvas.drawPath(path, mPaint);
        path.reset();
        viewMiddleX = newMiddleX;
        viewMiddleY = newMiddleY;
        statisticRegion(viewX0, viewY0);
        statisticRegion(viewX1, viewY1);
    }

    /**
     * 计算在板子原始坐标对应View上的坐标
     */
    private float[] calculateViewLocation(float[] coordinate) {
        float x = (coordinate[0] - firstPoint[0]) / ratio + getWidth() / 3;
        float y = (coordinate[1] - firstPoint[1]) / ratio + getHeight() / 3;
        System.out.println("xxxxxx  " + x + "yyyyyy  " + y);
        return new float[]{x, y};
    }

    /**
     * 单笔起笔
     */
    private void penDown(int x, int y) {
        paths.add(new SerializablePath());
        isWriting = true;
    }

    public void setBoardSize(int x, int y) {
        if (x != 0 && y != 0) {
            ratio = Math.max(x / getWidth(), y / getHeight());
            if (ratio < 1) {
                ratio = 1;
            }
        }
    }

    /**
     * 统计分析手写板书写的坐标最大和最小点
     */
    private void statisticRegion(float x, float y) {
        if (x < 0) {
            x = 0;
        }
        if (y < 0) {
            y = 0;
        }
        if (x > getWidth()) {
            x = getWidth();
        }
        if (y > getHeight()) {
            y = getHeight();
        }

        if (viewMinCoordinate[0] == -1) {
            viewMinCoordinate[0] = x;
        }
        if (-1 == viewMinCoordinate[1]) {
            viewMinCoordinate[1] = y;
        }
        if (-1 == viewMaxCoordinate[0]) {
            viewMaxCoordinate[0] = x;
        }
        if (-1 == viewMaxCoordinate[1]) {
            viewMaxCoordinate[1] = y;
        }


        if (x < viewMinCoordinate[0]) {
            viewMinCoordinate[0] = x;
        }
        if (y < viewMinCoordinate[1]) {
            viewMinCoordinate[1] = y;
        }
        if (x > viewMaxCoordinate[0]) {
            viewMaxCoordinate[0] = x;
        }
        if (y > viewMaxCoordinate[1]) {
            viewMaxCoordinate[1] = y;
        }
    }

    /**
     * 移动居中
     */
    public void move2Center() {
        float moveX = (viewMinCoordinate[0] + viewMaxCoordinate[0]) / 2 - getWidth() / 2;
        float moveY = (viewMinCoordinate[1] + viewMaxCoordinate[1]) / 2 - getHeight() / 2;

        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
//        canvas.drawColor(Color.TRANSPARENT);
        canvas.drawColor(Color.WHITE);
        mPaint.setAlpha(255);
        canvas.drawBitmap(mBitmap, -moveX, -moveY, mPaint);

        mCanvas.drawBitmap(bitmap, 0, 0, mPaint);
        invalidate();
    }

    /**
     * 裁剪居中
     */
    public void crop2Center() {
        float lengthOfX = viewMaxCoordinate[0] - viewMinCoordinate[0];
        float lengthOfY = viewMaxCoordinate[1] - viewMinCoordinate[1];
        float maxSide = lengthOfX > lengthOfY ? lengthOfX : lengthOfY;
        float moveX = (maxSide - lengthOfX) / 2;
        float moveY = (maxSide - lengthOfY) / 2;

        Bitmap bitmap = Bitmap.createBitmap((int) maxSide + 1, (int) maxSide + 1, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.TRANSPARENT);
        mPaint.setAlpha(255);
        canvas.drawBitmap(mBitmap, -viewMinCoordinate[0] + moveX, -viewMinCoordinate[1] + moveY, mPaint);

        mCanvas.drawBitmap(bitmap, 0, 0, mPaint);
        invalidate();
    }

    /**
     * 裁剪保存
     */
    public String crop2Save() {
        float lengthOfX = viewMaxCoordinate[0] - viewMinCoordinate[0];
        float lengthOfY = viewMaxCoordinate[1] - viewMinCoordinate[1];
        float maxSide = lengthOfX > lengthOfY ? lengthOfX : lengthOfY;
        float moveX = (maxSide - lengthOfX) / 2;
        float moveY = (maxSide - lengthOfY) / 2;

        Bitmap bitmap = Bitmap.createBitmap((int) maxSide + 4, (int) maxSide + 4, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.TRANSPARENT);
        mPaint.setAlpha(255);
        canvas.drawBitmap(mBitmap, -viewMinCoordinate[0] + moveX + 2, -viewMinCoordinate[1] + moveY + 2, mPaint);
        // TODO: 2018/3/25 耗时任务，应该放到后台
        return BitmapUtils.savePng(bitmap);
    }
}
